package com.qf.anno.advice;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import java.util.Arrays;

@Component
@Aspect  // 标识这个一个切面配置（切点--切点表达式找 + 通知--具体增强代码的编写位置）
public class DaoAdvice {

    //配置切点表达式
    @Pointcut("execution(* com.qf.anno.dao.*.*(..))")
    public void pt(){}

    @Pointcut("execution(* *..*.*(..))")
    public void pt2(){}

//    @Before("pt()")  //前置通知
    public void before(JoinPoint jp){
        Object[] args = jp.getArgs();
        System.out.println(Arrays.toString(args));
        System.out.println("before~~");
    }

//    @After("pt()") //最终通知，相当于写到finally代码块中的
    public void after(){
        System.out.println("after~~");
    }

//    @AfterReturning(value = "pt()",returning = "result") //返回后通知，相当于写在try代码块中的，目标方法正常执行，才会执行
    //返回后通知中，可以获取目标方法的返回值
    public void afterReturning(Object result){
        System.out.println("afterReturning~~");

        System.out.println("目标方法执行完后的返回值：" + result);
    }

//    @AfterThrowing(value = "pt()",throwing = "e") //异常通知，相当于写在catch代码块中的，目标方法抛出异常，才会执行
    //异常通知中，可以获取到目标方法的异常信息
    public void afterThrowing(Throwable e){
        System.out.println("afterThrowing~~");

        System.out.println(e.getMessage());
    }

    @Around("pt()")
    /*环绕如果不设置返回值，那么在增强有返回值的目标方法时，会出现报错
        Null return value from advice does not match primitive return type for:
        public abstract int com.qf.anno.dao.UserDao.delete(java.lang.Integer)

        ** 原始delete方法返回值是int，而现在我们环绕通知方法的返回值void，导致返回值不匹配，所以报错
     */
    public Object around(ProceedingJoinPoint pjp){

        try {
            Object result = pjp.proceed();

            System.out.println(result);
            return result;
        } catch (Throwable e) {
            e.printStackTrace();
        }finally{

        }
        return null;
    }
}
